<template>
  <div class="picker-left-search">
    <a-input v-model="keywords" :placeholder="mode | placeholder" allowClear @change="handleSearch">
      <a-icon slot="prefix" type="search" />
    </a-input>
    <div class="search-result" v-if="active">
      <template v-if="mode.includes('member')">
        <div class="search-result-title" v-if="memberResult.length > 0">成员</div>
        <ul class="search-result-list" v-for="user in memberResult" :key="`member${user[UserPickerOptions.id]}`">
          <li
            :class="[
              'search-result-item',
              'search-result-user',
              { 'search-result-item-selected': selectedKeys.includes(`member${user[UserPickerOptions.id]}`) }
            ]"
            @click="handleSelect(`member${user[UserPickerOptions.id]}`)"
          >
            <span class="search-result-user-username">{{ user[searchMemberProp] }}</span>
            <span
              class="search-result-user-department"
              :title="user[UserPickerOptions.relationId] | partyOfMember(party, searchPartyProp)"
            >{{ user[UserPickerOptions.relationId] | partyOfMember(party, searchPartyProp) }}</span
            >
          </li>
        </ul>
      </template>
      <template v-if="mode.includes('party')">
        <div class="search-result-title" v-if="partyResult.length > 0">部门</div>
        <ul
          class="search-result-list"
          v-for="department in partyResult"
          :key="`party${department[UserPickerOptions.id]}`"
        >
          <li
            :class="[
              'search-result-item',
              'search-result-department',
              { 'search-result-item-selected': selectedKeys.includes(`party${department[UserPickerOptions.id]}`) }
            ]"
            @click="handleSelect(`party${department[UserPickerOptions.id]}`)"
          >
            <a-icon class="search-result-department-icon" type="folder" />
            <span class="search-result-department-name">{{ department[searchPartyProp] }}</span>
          </li>
        </ul>
      </template>
    </div>
  </div>
</template>

<script>
import debounce from 'lodash.debounce'
import { UserPickerOptions } from './options'

export default {
  name: 'UserPickerSearch',
  data () {
    return {
      active: false,
      keywords: '',
      partyResult: [],
      memberResult: [],
      UserPickerOptions
    }
  },
  props: {
    mode: {
      type: Array,
      default: ['member', 'party']
    },
    party: {
      type: Array,
      default: []
    },
    member: {
      type: Array,
      default: []
    },
    // 搜索部门的字段
    searchPartyProp: {
      type: String,
      default: 'name'
    },
    // 搜索成员的字段
    searchMemberProp: {
      type: String,
      default: 'name'
    },
    // 开启拼音搜索，拼音全称pinyin，首字母缩写py
    searchPinyin: {
      type: Boolean,
      default: true
    },
    pinyin: {
      type: String,
      default: 'pinyin'
    },
    py: {
      type: String,
      default: 'py'
    },
    // 已选择的人员或部门
    selectedKeys: {
      type: Array,
      default: []
    }
  },
  watch: {
    keywords (value) {
      this.active = !!value.trim()
      this.$emit('change', !!this.keywords)
    }
  },
  filters: {
    // 搜索描述
    placeholder (mode) {
      if (mode.includes('member') && mode.includes('party')) {
        return '搜索部门、成员'
      } else if (mode.includes('member')) {
        return '搜索成员'
      } else if (mode.includes('party')) {
        return '搜索部门'
      } else {
        return '搜索'
      }
    },
    // 人员所在的部门
    partyOfMember (partyId, party, partyProp) {
      if (partyId && typeof partyId !== 'number') {
        const partys = []
        partyId.forEach(element => {
          const targetParty = party.find(item => item[UserPickerOptions.id] == element)
          partys.push(targetParty ? targetParty[partyProp] : '未知部门')
        })
        return partys.join()
      } else {
        const targetParty = party.find(item => item[UserPickerOptions.id] == partyId)
        return targetParty ? targetParty[partyProp] : '未知部门'
      }
    }
  },
  methods: {
    handleSearch: debounce(function (e) {
      const keywords = e.target.value.trim()
      if (keywords) {
        // 搜索成员
        if (this.mode.includes('member')) {
          this.memberResult = this.getResult(keywords, 'member')
        }
        // 搜索部门
        if (this.mode.includes('party')) {
          this.partyResult = this.getResult(keywords, 'party')
        }
      } else {
        // 无搜索内容时，自动清楚搜索状态
        this.keywords = ''
        this.partyResult = []
        this.memberResult = []
      }
    }, 500),
    /**
     * 搜索内容
     */
    getResult (value, type) {
      const list = type === 'member' ? this.member : this.party
      const field = type === 'member' ? this.searchMemberProp : this.searchPartyProp
      const keywords = value.toUpperCase()
      const result = list.filter(item => {
        const targetValue = (item[field] || '').toUpperCase()
        let validate = targetValue.indexOf(keywords) > -1

        if (!validate && this.searchPinyin) {
          const pinyinStr = (item[this.pinyin] || '').replace(/,/g, '').toUpperCase()
          const pyStr = (item[this.py] || '').replace(/,/g, '').toUpperCase()
          validate = pinyinStr.indexOf(keywords) > -1 || pyStr.indexOf(keywords) > -1
        }

        return validate
      })
      if (type === 'member') {
        const finalResult = this.mergeOrgName(result, 'id') // 重复的人员去重 合并部门名 （适用于一个人在多部门情况）
        return finalResult
      }
      return result
    },
    mergeOrgName (result, key) {
      const hash = {}
      return result.reduce((ss, item) => {
        // reduce累计器, ss是具体满足条件后返回的数据, item是数组依次循环的每一项
        // 1、判断对象的键值是否存在
        hash[item[key]]
          ? ss.map(d => {
            if (item[key] === d[key]) {
              // 如果之前里面已经有值了 则把orgId变成数组合并
              if (typeof d.orgId === 'number') {
                return (d.orgId = [d.orgId, item.orgId])
              } else {
                d.orgId.push(item.orgId)
                return (d.orgId = Array.from(new Set(d.orgId)))
              }
            }
            return d
          })
          : (hash[item[key]] = true && ss.push(item))
        return ss
      }, [])
    },
    // 选择搜索项
    handleSelect (key) {
      this.$emit('onSelect', key)
      this.clearSearch()
    },
    clearSearch () {
      this.keywords = ''
      this.partyResult = []
      this.memberResult = []
    }
  }
}
</script>

<style lang="less" scoped>
.picker-left-search {
  padding-right: 20px;
  margin-bottom: 10px;
  font-size: 13px;

  .search-result {
    margin-top: 10px;
    &-list {
      padding: 0;
      margin: 0;
    }
    &-title {
      margin: 5px 12px 0;
      height: 30px;
      line-height: 30px;
      color: #787878;
    }
    &-item {
      height: 30px;
      line-height: 30px;
      padding: 0 12px;
      white-space: nowrap;
      overflow: hidden;
      text-overflow: ellipsis;
      cursor: pointer;

      &:hover {
        background-color: #f2f2f2;
      }

      &-selected {
        pointer-events: none;
        opacity: 0.5;
      }
    }
    &-user {
      &-username {
        width: 50%;
        float: left;
        padding-right: 7px;
        overflow: hidden;
        text-overflow: ellipsis;
      }
      &-department {
        display: block;
        text-align: right;
        overflow: hidden;
        text-overflow: ellipsis;
      }
    }
    &-department {
      &-icon {
        font-size: 16px;
      }
      &-name {
        margin-left: 5px;
      }
    }
  }
}
</style>
